#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>  //#include <QMainWindow>
#include <QtSerialPort/qserialport.h>
#include "mb_protocol.h"
#include "tf_modbus.h"
#include <QThread>

#include <memory>
#include <thread>

#include <QMutex>
//#include <QModbusClient> //LM add@2020-09-8 from third party

//#include <QModbusRtuSerialMaster>

extern bool is_run;
extern quint16 GC_read_status; //2     indicate unknown status  0:ready  1: Not-ready



#define WINDOW_TITLE "Preconcentrate V-04.04        ThermoFisher-Scientific     liu.ming@2021-06-16       GC-V3"
#define UART_BUFFER_MAX 150

#define MFC_MB_SLAVE_ID 0x01
#define EPC_MB_SLAVE_ID 0x02
#define MFC_SEVEN_SLAVE_ID   0x03  //#1 SevenStar MFC
#define MFC_SEVEN_SLAVE_ID_2 0x04  //#2 SevenStar MFC
#define MIDWAY_MB_SLAVE_ID 0x01

#define addr_EPC_Press_channel_1  1555
#define addr_EPC_Press_channel_2  1559
#define addr_EPC_Press_channel_3  1563

namespace Ui {
class MainWindow;
}


typedef enum{
     err_none = 0,
     err_disconected,

 }ERR_STATUS;


typedef struct {
    float epc_press[3];
    float epc_flow[3];
} EPCInfo;

typedef struct {
    int InitializationStus; //0:Not  1: OK
    int PurgeDehydrationStus;
    int PurgeConcentrationAStus;
    int PurgeConcentrationBStus;
    int PurgeFocusingStus;
    int PreSampleAStus;
    int PreSampleBStus;
    int SampleAStus;
    int SampleBStus;
    int PrePurgeAStus;
    int PrePurgeBStus;
    int ConTrapFireAStus;
    int ConTrapFireBStus;
    int FocusTrapFireStus;
    int StandardAStus;
    int StandardBStus;
    int GC_readStus;


} SUB_ModStus;

typedef struct {

    SUB_ModStus subModStus;
    EPCInfo epcInfo;
    float MFC_value;

} GlobalInfo;

extern GlobalInfo glabalInfo;





class myThread : public QThread
{

    Q_OBJECT
public:
    explicit myThread(QObject *parent = 0);
    ~myThread()
    {
        qDebug()<<" ~myThread()"<<endl;
    }

//protected:
    void run();  //重写父类的虚函数 run


/* ________________________________*/
    void Initialization_wait()
    {
        while(!glabalInfo.subModStus.InitializationStus)
        {
            QThread::msleep(1);
        }
        glabalInfo.subModStus.InitializationStus = 0;
    }
    void PurgeDehydration_wait()
    {
        while(!glabalInfo.subModStus.PurgeDehydrationStus)
        {
            QThread::msleep(1);
        }
        glabalInfo.subModStus.PurgeDehydrationStus = 0;
    }
    void PurgeConcentrationA_wait()
    {
        while(!glabalInfo.subModStus.PurgeConcentrationAStus)
        {
            QThread::msleep(1);
        }
        glabalInfo.subModStus.PurgeConcentrationAStus = 0;
    }
    void PurgeConcentrationB_wait()
    {
        while(!glabalInfo.subModStus.PurgeConcentrationBStus)
        {
            QThread::msleep(1);
        }
        glabalInfo.subModStus.PurgeConcentrationBStus = 0;
    }
    void PurgeFocusing_wait()
    {
        while(!glabalInfo.subModStus.PurgeFocusingStus)
        {
            QThread::msleep(1);
        }
        glabalInfo.subModStus.PurgeFocusingStus = 0;
    }
    void PreSampleA_wait()
    {
        while(!glabalInfo.subModStus.PreSampleAStus)
        {
            QThread::msleep(1);
        }
        glabalInfo.subModStus.PreSampleAStus = 0;
    }
    void PreSampleB_wait()
    {
        while(!glabalInfo.subModStus.PreSampleBStus)
        {
            QThread::msleep(1);
        }
        glabalInfo.subModStus.PreSampleBStus = 0;
    }
    void SampleA_wait()
    {
        while(!glabalInfo.subModStus.SampleAStus)
        {
            QThread::msleep(1);
        }
        glabalInfo.subModStus.SampleAStus = 0;
    }
    void SampleB_wait()
    {
        while(!glabalInfo.subModStus.SampleBStus)
        {
            QThread::msleep(1);
        }
        glabalInfo.subModStus.SampleBStus = 0;
    }
    void PrePurgeA_wait()
    {
        while(!glabalInfo.subModStus.PrePurgeAStus)
        {
            QThread::msleep(1);
        }
        glabalInfo.subModStus.PrePurgeAStus = 0;
    }
    void PrePurgeB_wait()
    {
        while(!glabalInfo.subModStus.PrePurgeBStus)
        {
            QThread::msleep(1);
        }
        glabalInfo.subModStus.PrePurgeBStus = 0;
    }
    void ConTrapFireA_wait()
    {
        while(!glabalInfo.subModStus.ConTrapFireAStus)
        {
            QThread::msleep(1);
        }
        glabalInfo.subModStus.ConTrapFireAStus = 0;
    }
    void ConTrapFireB_wait()
    {
        while(!glabalInfo.subModStus.ConTrapFireBStus)
        {
            QThread::msleep(1);
        }
        glabalInfo.subModStus.ConTrapFireBStus = 0;
    }
    void FocusTrapFire_wait()
    {
        while(!glabalInfo.subModStus.FocusTrapFireStus)
        {
            QThread::msleep(1);
        }
        glabalInfo.subModStus.FocusTrapFireStus = 0;
    }
    void StandardA_wait()
    {
        while(!glabalInfo.subModStus.StandardAStus)
        {
            QThread::msleep(1);
        }
        glabalInfo.subModStus.StandardAStus = 0;
    }
    void StandardB_wait()
    {
        while(!glabalInfo.subModStus.StandardBStus)
        {
            QThread::msleep(1);
        }
        glabalInfo.subModStus.StandardBStus = 0;
    }
    void ReadGC_Stus_wait()
    {
        while(!glabalInfo.subModStus.GC_readStus)
        {
            QThread::msleep(1);
        }
        glabalInfo.subModStus.GC_readStus = 0;
    }


signals:
    void sig_ReadEPC(quint8 EPC_mode); //0-> press mode  1: Flow mode
    void sig_setValve(quint8 channel_num, quint16 valve_status);
    void sig_setEPC(quint8 , float );
    void sig_setTEC(quint8 channel_num, float temperature);
    void sig_setMFC(quint16 numOf_sccm);
    void sig_setHeater(quint8 channel_num, float num_of_seconds);
    void sig_setGC(bool on_off);
    void sig_readGC_stus();
    void sig_setHeatingTube(quint8 channel_num, float target_temperature);
    void sig_Initialization();


    void sig_PurgeDehydration();
    void sig_PurgeConcentrationA();
    void sig_PurgeConcentrationB();
    void sig_PurgeFocusing();
    void sig_PreSampleA();
    void sig_PreSampleB();
    void sig_SampleA();
    void sig_SampleB();
    void sig_PrePurgeA();
    void sig_PrePurgeB();
    void sig_ConTrapFireA();
    void sig_ConTrapFireB();
    void sig_FocusTrapFire();
    void sig_StandardA();
    void sig_StandardB();
};


//class MainWindow : public QMainWindow, QModbusClient  MainWindow
class MainWindow : public QMainWindow, tf_modbus
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    enum {
        EPC_MODE_PRESS,
        EPC_MODE_FLOW
    };


    enum {


        addr_Mid_readGCTemp = 52,
        addr_Mid_readTransferTemp = 54,

        addr_Mid_targetTransferSetTemp = 1566,// target temp
        addr_Mid_targetGCSetTemp = 1574,      // target temp

        addr_valve_NO_1 = 1544,
        addr_valve_NO_2 = 1545,
        addr_valve_NO_3 = 1546,
        addr_valve_NO_4 = 1547,
        addr_valve_NO_5 = 1548,
        addr_valve_NO_6 = 1549,
        addr_valve_NO_7 = 1550,
        addr_valve_NO_8 = 1551,

        addr_Mid_Heater0_UMB_ON = 1554,     //Heater-0
        addr_Mid_Heater0_UMB_time = 1555,
        addr_Mid_Heater1_ProBlo_ON = 1556,  //Heater-1
        addr_Mid_Heater1_ProBlo_time = 1557,
        addr_Mid_Heater2_ProFil_ON = 1558,  //Heater-2
        addr_Mid_Heater2_ProFil_time = 1559,
        addr_Mid_Heater3_Sting_ON = 1560,   //Heater-3
        addr_Mid_Heater3_Sting_time = 1561,
    };

    void Log(QString str);



private slots:
    void fillPortsInfo(uint8_t whichPort);
    void checkPortsInfo(uint8_t whichPort);
    //void handleError(QSerialPort::SerialPortError error);
    //void uartSend(unsigned char *buf,int buf_Len);
    //void recv_handler();
    //void recvTimeout();
    void periodic_timeout();
    void epc_mfc_timeout();

    void on_BT_Connect_Mid_clicked();
    void on_refresh_com_Mid_sliderPressed();

    void on_BT_Connect_EPC_MFC_clicked();

    void on_BT_Connect_TEC_1_clicked();

    void on_BT_Connect_TEC_2_clicked();

    void on_refresh_com_EPC_sliderPressed();

    void on_refresh_com_TEC_1_sliderPressed();

    void on_refresh_com_TEC_sliderPressed();

    void on_checkBox_ContinueRead_TEC_1_clicked(bool checked);

    void on_BT_TEC1_start_clicked();

    void on_BT_TEC1_stop_clicked();

    void on_BT_TEC1_setT_clicked();

    void on_BT_clearLog_clicked();

    void on_BT_MFC_setFlow_clicked();

    void on_checkBox_ContinueRead_MFC_clicked(bool checked);

    void on_BT_TEC_2_start_clicked();

    void on_BT_TEC_2_stop_clicked();

    void on_checkBox_ContinueRead_TEC2_clicked(bool checked);

    void on_BT_TEC_2_setT_clicked();

    void on_checkBox_valve_1_clicked(bool checked);

    void on_checkBox_valve_2_clicked(bool checked);

    void on_checkBox_valve_3_clicked(bool checked);

    void on_checkBox_valve_4_clicked(bool checked);

    void on_checkBox_valve_5_clicked(bool checked);

    void on_checkBox_valve_6_clicked(bool checked);

    void on_checkBox_valve_7_clicked(bool checked);

    void on_BT_EPC_setFlow_1_clicked();

    void on_BT_EPC_setFlow_2_clicked();

    void on_BT_EPC_setFlow_3_clicked();

    void on_checkBox_ContinueRead_EPC_clicked(bool checked);

    void on_horizontalSlider_A_sliderMoved(int position);

    void on_horizontalSlider_B_sliderMoved(int position);



    void on_BT_setTimHeate_A_clicked();

    void on_BT_setTimHeate_B_clicked();

    void on_BT_openScript_clicked();

    void window_destroyed_handle();


    void on_BT_Trig_clicked();

    void on_BT_PressStop_clicked();


    /*  FangJun 控制部分 */
    //void setValve(quint8 channel_num, quint16 valve_status);
    void setValve(quint8 channel_num, quint16 valve_status);
    void setEPC(quint8 channel_num, float setValue);
    void ReadEPC(quint8 EPC_mode);
    void ReadMFC();

    void setTEC(quint8 channel_num, float temperature);
    void setTEC(quint8 channel_num, QString temperature); //重载
    void setMFC(quint16 numOf_sccm);
    void setHeater(quint8 channel_num, float num_of_seconds);
    void setHeatingTube(quint8 channel_num, float target_temperature);

    void setGC(bool ON_OFF);
    void readGC_stus(); //槽

    void on_comboBox_EPC_mode_currentIndexChanged(int index);


    void on_BT_TransferHotLine_setT_clicked();


/*++++++++++ Module Control +++++++++++*/
    void Initialization();
    void PurgeDehydration();
    void PurgeConcentrationA();
    void PurgeConcentrationB();
    void PurgeFocusing();
    void PreSampleA();
    void PreSampleB();
    void SampleA();
    void SampleB();
    void PrePurgeA();
    void PrePurgeB();
    void ConTrapFireA();
    void ConTrapFireB();
    void FocusTrapFire();
    void StandardA();
    void StandardB();

    // std::thread interface
    ERR_STATUS readGC_stus2();
    ERR_STATUS StandardB2();

    void on_BT_Connect_TEC_0_clicked();

    void on_refresh_com_TEC_0_sliderPressed();

    void on_BT_TEC_0_start_clicked();

    void on_BT_TEC_0_stop_clicked();

    void on_BT_TEC_0_setT_clicked();

    void on_checkBox_ContinueRead_TEC0_clicked(bool checked);

    void on_checkBox_ContinueRead_transfer_hotline_clicked(bool checked);

    void on_BT_GCHotLine_setT_clicked();


    void on_horizontalSlider_C_sliderMoved(int position);

    void on_horizontalSlider_D_sliderMoved(int position);

    void on_BT_setTimHeate_C_clicked();

    void on_BT_setTimHeate_D_clicked();

    void on_checkBox_valve_8_clicked(bool checked);

    void on_BT_GC_ON_clicked();

    void on_BT_GC_OFF_clicked();

    void on_checkBox_ContinueRead_GC_clicked(bool checked);

    void on_comboBox_MFC_mode_currentIndexChanged(int index);

    void on_BT_MFC_setFlow_2_clicked();

protected:


private:
    //QSerialPort *uart;
    Ui::MainWindow *ui;
    bool Midway_isOpened = false;
    bool EPC_MFC_isOpened = false;
    bool TEC_0_isOpened = false;
    bool TEC_1_isOpened = false;
    bool TEC_2_isOpened = false;

    QString comPort;

    QString hexString2QString( uint8_t *buff, int16_t len);

    uint8_t sendBuf[20];
    uint8_t recvBuf[UART_BUFFER_MAX];
    QByteArray recvArr;
    //QTimer *recvTick;
  //  QTimer *periodicTick; //lm test
    std::shared_ptr<QTimer> periodicTick;
    std::shared_ptr<QTimer> timer_epc_mfc;
    //QTimer *timer_epc_mfc;

    uint8_t device_ID;

    void MainWindow_log(uint8_t *buf, int buf_Len);
    void MainWindow_log(char *buf);

    uint8_t MFC_type = 0; //0:default  1: SevenStar
    uint8_t mfc_read_status = 0;
    uint8_t epc_read_status = 0;
    uint8_t TEC_0_read_status = 0;
    uint8_t TEC_1_read_status = 0;
    uint8_t TEC_2_read_status = 0;
    uint8_t HotLine_readStus = 0; //1: continuous read   0: not read
    bool GC_readStatus = false;

    //myThread *qthread;
    std::shared_ptr<myThread> qthread;

    void thread_run();
    std::unique_ptr<std::thread> std_thread;
    std::mutex trig_mutex;
    std::condition_variable cv;
    bool threadTrigFlag = false;

    int epc_mode_index = 0; //1: flow mode   0: press mode

  //  QMutex *mutex_midway;
//    QMutex *mutex_epcmfc;
//    QMutex *mutex_tec_1;
//    QMutex *mutex_tec_2;
    std::shared_ptr<QMutex> mutex_midway;
    std::shared_ptr<QMutex> mutex_epcmfc;
    std::shared_ptr<QMutex> mutex_tec_0; //new add for Purge
    std::shared_ptr<QMutex> mutex_tec_1;
    std::shared_ptr<QMutex> mutex_tec_2;
};




/*+++++++++++++++++++++++++ Modbus Regs ++++++++++++++++++++++++*/

/* max read and write register count */
#define MAX_RAM_WRITE_REGS			100//10  LM exchanged
#define MAX_RAM_READ_REGS			5   //we don't want this to make the struc bigger than necessary

typedef struct Dat_ramDb
{
    /* Common data to all input board. TBD: Modbus address */
    /* The strcuture is reserved for things that don't need to be read every second */
    /* Read/write registers. Address range: 0x0200 to 0x03FD */
    struct
    {
        /* Important: any changes to the info block should be reflected in functions build_info_block() and read_saved_info() */

        /* 125 is the maximum number of registers allowed by Modbus, See documenet: "FS Einstein internal Protocol.doc"*/
        /* This block is password protected */
        U16 board_type;

        /* application version number */
        U16 major_fw_ver;
        U16 minor_fw_ver;
        U16 maint_fw_ver;
        U16 build_fw_ver;

        /* application version number */
        U16 major_bloader_ver;
        U16 minor_bloader_ver;
        U16 maint_bloader_ver;
        U16 build_bloader_ver;

        /* Module Serial number */
        U16 serial_number_char[8]; /* 16 char. alpha-numeric string */

        /* Sub_type: 1 = MODEL_42_STD, 2=HL, 3=TL, 4=LS, 5=NOY, 6=J, 7=17, 8=NOx, 9=G */
        U16 sub_type;

        /* PID coefficients for heater temperature */
        F32 HTR_temp_PID_P;
        F32 HTR_temp_PID_I;
        /* PID coefficients for cooler temperature */
        F32 cooler_temp_PID_P;
        F32 cooler_temp_PID_I;

        /* Up time registers */
        /* TBD: Should I have a copy of uptime here */
        U16 uptime_days;
        /* Turn usci_a0 communication watchdog ON/OFF */
        U16 uart_a0_comm_watchdog;

        U16 spare[97]; /* 97 = (125-1) - (1+4+4+8+(4*2)+1+1) */

    } read_write_info;

    /* Address: 0x3FE */
    U32 password; /* password is used to restrict write access to 0x0200-0x03FD block (module info) */

    /* Read/write registers. Address range: 0x0800 to 0x09FF */
    struct
    {
        /* 125 is the maximum number of registers allowed by Modbus, See documenet: "FS Einstein internal Protocol.doc"*/
        /* calibration fault registers */
           U16 	  	cal_fault0;
           U16 	  	cal_fault1;

       F32		board_temp_offset;
       F32		flow1_temp_offset;
       F32		flow2_temp_offset;
       F32		amb_temp_offset;

       F32		rh_offset;

       F32		bar_pres_offset;
       F32		bar_pres_slope;

       F32		flow1_pres_offset;
       F32		flow1_pres_slope;

       F32		vac1_pres_offset;
       F32		vac1_pres_slope;

    } read_write_cal;

    /* output registers */
    /* Read only registers. Address range: 0x0000 to 0x01FF */
    union
    {
        U16 registers[MAX_RAM_WRITE_REGS];
        U8  bytes[MAX_RAM_WRITE_REGS * sizeof(U16)];
/* front end 5014i input */
        struct
        {
          struct
            {
                /* A copy of Struct "state" exists in bootloader code */
                /* NB: When you modify struct "state" here make sure to modify struct "state"
                       the same way in database.h in bootloader */
                U16 BootloaderMode; /* 0=BL with invalid App, 1=BL with valid App, 2=App */

                /* fault registers */
                U16 fault_0;
                U16 fault_1;
                U16 fault_2;
                U16 fault_3;

                /* Up time registers */
                U16 uptime_days; //5
            } state;

            U16 load_motor;	   //LM add  addr=6
            U32 detector_freq;  //*buf[17]  addr=7
            /*For 5014, there are 24 ADC channels. The data is written to
             *data_ram.write_.fe_5014.analog_in[channel_idx] one by one.
             *The data in analog_in[] is strictly mapped to hardware connection
             *Here is the mapping for 5014i and 5028i hardware
             *0=spare, 1=PRESS_TEMP, 2/3/4=spare, 5=-12V_MONITOR, 6=+12V_MONITOR
             *7=spare, 8=BOARD_THERM,
             *9=-15V Power Monitor, 10= 24V, 11=15V, 12=5V, 13=3.3V
             *14=flow_temp1, 15=flow_temp2, 16=RTDT_TEMP, 17=RHP_hum, 18=Bar_press
             *19=flow_1, 20:vac_1_press, 21:flow_2, 22:vac_2_press
             *23:spare_pressure in 5014i, BATT_5V_MONITOR in 5028i
             */
            F32 analog_in[24];  //addr=9+24*2-1=
            U16 analog_in_3p3V;     // new variable for 3.3 V   addr=57
            U16 tape_counts;    //addr=58

        } fe_5014;
    } write;

    /* input registers */
    /* Read only registers. Address range: 0x0600 to 0x07FF */
    union
    {
        U16 registers[MAX_RAM_READ_REGS];
        U8  bytes[MAX_RAM_READ_REGS * sizeof(U16)];

/* 5014 beta board output */
        struct
        {
            U16 BootloadModeCmd;  //1536

            U16 SOLENOID_VALVE1DC_ON; //1537     J22
            U16 SOLENOID_VALVE2DC_ON; //1538	 J18
            U16 PUMP1_ON;	      //1539	 J8
            U16 CNTRL1_ON;            //1540   cam motor
            U16 CNTRL2_ON;   	      //1541
            U16 FAN_ON;    	      //1542

            U16 analog_out[2];  //LM changed 3 to 2

            /* other calibrations such as temperatures, pressures, etc... */
            U16 cal_action; /* calibration steps */ //*LM Add From 42PMT
            F32 cal_target; /* Target value as entered by user */ //*LM Add From 42PMT

    /*++++++++++++++++ Neph cmd ++++++++++++++++++*/
            U16 spare;  				//1548
            U16 command_number;			//1549
            signed long	command_value;  //1550
    /*++++++++++++++++ Neph end ++++++++++++++++++*/
        } fe_5014;

    } read;

//    // FW update start at 0x0A00, up to 0x0BFF
//    struct
//    {
//        U16 Func;
//        U32 Addr;
//        U16 NumBytes;
//        U16 Words[119];
//    } FWUpdate;
} Dat_ramDb;


#endif // MAINWINDOW_H
